package gui;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

import parser.Block;
import parser.FloorPlan;
import parser.FloorPlanParser;
import parser.ParseResult;
import simuAnnealing.SAconfigurations;
import simuAnnealing.SimulatedAnnealing;
import simuAnnealing.Solution;
import simuAnnealing.Solution.alogrithmToUse;

import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import java.awt.Font;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.awt.Color;
import java.awt.Dialog.ModalExclusionType;

import java.awt.SystemColor;
import javax.swing.JButton;
import javax.swing.JProgressBar;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.ImageIcon;
import javax.swing.SwingConstants;

public class MainPage extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	// GraphicalBlockRepresentation blockPresentation;
	FloorPlan initialFloorPlan;
	Solution soluion;
	private JFrame myFrame;
	private JTextField initialResult;
	private JTextField finalResullt;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MainPage frame = new MainPage();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public MainPage() {

		myFrame = this;
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		this.setResizable(false);
		this.setSize(640, 480);
		this.setLocationRelativeTo(null);
		this.setUndecorated(true);

		JMenuBar menuBar = new JMenuBar();
		menuBar.setBackground(SystemColor.inactiveCaptionBorder);
		menuBar.setFont(new Font("Segoe UI", Font.PLAIN, 15));
		setJMenuBar(menuBar);

		JMenu mnFile = new JMenu("File");
		mnFile.setFont(new Font("Segoe UI", Font.PLAIN, 15));
		menuBar.add(mnFile);

		JMenuItem insertFileInput = new JMenuItem(
				"Choose Initial FP (Solution)");
		insertFileInput.setFont(new Font("Segoe UI", Font.PLAIN, 15));
		mnFile.add(insertFileInput);
		insertFileInput.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
				java.awt.event.KeyEvent.VK_O,
				java.awt.event.InputEvent.CTRL_MASK));

		JMenuItem exitTheApp = new JMenuItem("Exit");
		exitTheApp.setFont(new Font("Segoe UI", Font.PLAIN, 15));
		mnFile.add(exitTheApp);

		exitTheApp.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
				java.awt.event.KeyEvent.VK_F4,
				java.awt.event.InputEvent.ALT_MASK));

		exitTheApp.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				System.exit(0);
			}
		});

		JMenu mnDisplay = new JMenu("Display");
		mnDisplay.setFont(new Font("Segoe UI", Font.PLAIN, 15));
		menuBar.add(mnDisplay);

		JMenuItem mntmSimulatedAnnealingResult = new JMenuItem(
				"Draw Floor-Plan");

		mntmSimulatedAnnealingResult.setFont(new Font("Segoe UI", Font.PLAIN,
				15));
		mnDisplay.add(mntmSimulatedAnnealingResult);

		JMenuItem btnShowGraph = new JMenuItem(
				"Graph of cost as a function of state");

		btnShowGraph.setFont(new Font("Segoe UI", Font.PLAIN, 15));
		mnDisplay.add(btnShowGraph);

		JMenu mnEdit = new JMenu("Edit");
		mnEdit.setFont(new Font("Segoe UI", Font.PLAIN, 15));
		menuBar.add(mnEdit);

		JMenuItem updateConfigsBtn = new JMenuItem("Algorithms configurations");
		updateConfigsBtn.setFont(new Font("Segoe UI", Font.PLAIN, 15));
		mnEdit.add(updateConfigsBtn);

		updateConfigsBtn.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				configurationsUpdateDialog();

			}
		});

		final JPanel panel = new JPanel();
		panel.setBackground(new Color(51, 102, 153));
		GroupLayout groupLayout = new GroupLayout(getContentPane());
		groupLayout.setHorizontalGroup(groupLayout.createParallelGroup(
				Alignment.LEADING).addComponent(panel, Alignment.TRAILING,
				GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE));
		groupLayout.setVerticalGroup(groupLayout.createParallelGroup(
				Alignment.LEADING).addComponent(panel,
				GroupLayout.DEFAULT_SIZE, 277, Short.MAX_VALUE));

		JLabel lblPowerawareFloorplanning = new JLabel(
				"Power-Aware FloorPlanning");
		lblPowerawareFloorplanning.setForeground(SystemColor.window);
		lblPowerawareFloorplanning.setFont(new Font("Times New Roman",
				Font.PLAIN, 36));

		JLabel label = new JLabel("");

		final JLabel lblInitialSolutionWas = new JLabel(
				"Initial solution was created successfully click to run SA");
		lblInitialSolutionWas.setForeground(SystemColor.window);
		lblInitialSolutionWas.setFont(new Font("Tahoma", Font.PLAIN, 14));
		lblInitialSolutionWas.setVisible(false);

		final JButton btnRunSA = new JButton("");
		btnRunSA.setBorder(BorderFactory.createEmptyBorder());
		btnRunSA.setContentAreaFilled(false);

		btnRunSA.setIcon(new ImageIcon(MainPage.class
				.getResource("/Images/Run.png")));
		btnRunSA.setVisible(false);

		final JLabel lblSimulatedAnnealingResults = new JLabel(
				"Simulated Annealing results:");
		lblSimulatedAnnealingResults.setForeground(Color.ORANGE);
		lblSimulatedAnnealingResults.setFont(new Font("Times New Roman",
				Font.BOLD, 16));
		lblSimulatedAnnealingResults.setVisible(false);

		final JLabel lblInitialFpsolution = new JLabel(
				"Initial FP (Solution) power cost");
		lblInitialFpsolution
				.setFont(new Font("Times New Roman", Font.PLAIN, 13));
		lblInitialFpsolution.setForeground(SystemColor.window);
		lblInitialFpsolution.setVisible(false);

		initialResult = new JTextField();
		initialResult.setColumns(10);

		final JLabel lblFinalFpsolution = new JLabel(
				"Final FP power cost (Result)");
		lblFinalFpsolution.setFont(new Font("Times New Roman", Font.PLAIN, 14));
		lblFinalFpsolution.setForeground(SystemColor.window);
		lblFinalFpsolution.setVisible(false);

		finalResullt = new JTextField();
		finalResullt.setColumns(10);

		initialResult.setVisible(false);
		finalResullt.setVisible(false);

		final JLabel lblClickToRun = new JLabel(
				"Click to run Simulated Annealing again (this may affect the results above)");
		lblClickToRun.setHorizontalAlignment(SwingConstants.RIGHT);
		lblClickToRun.setForeground(Color.WHITE);
		lblClickToRun.setFont(new Font("Tahoma", Font.PLAIN, 14));
		lblClickToRun.setVisible(false);

		final JButton repeatSA = new JButton("");
		repeatSA.setIcon(new ImageIcon(MainPage.class
				.getResource("/Images/repeat.png")));
		repeatSA.setBorder(BorderFactory.createEmptyBorder());
		repeatSA.setContentAreaFilled(false);
		repeatSA.setVisible(false);

		GroupLayout gl_panel = new GroupLayout(panel);
		gl_panel.setHorizontalGroup(gl_panel
				.createParallelGroup(Alignment.TRAILING)
				.addGroup(
						gl_panel.createSequentialGroup()
								.addGroup(
										gl_panel.createParallelGroup(
												Alignment.LEADING)
												.addGroup(
														gl_panel.createSequentialGroup()
																.addGap(292)
																.addComponent(
																		label))
												.addGroup(
														gl_panel.createSequentialGroup()
																.addGap(123)
																.addGroup(
																		gl_panel.createParallelGroup(
																				Alignment.LEADING)
																				.addComponent(
																						lblPowerawareFloorplanning)
																				.addGroup(
																						gl_panel.createSequentialGroup()
																								.addPreferredGap(
																										ComponentPlacement.RELATED)
																								.addGroup(
																										gl_panel.createParallelGroup(
																												Alignment.LEADING)
																												.addComponent(
																														lblSimulatedAnnealingResults)
																												.addGroup(
																														gl_panel.createParallelGroup(
																																Alignment.TRAILING)
																																.addGroup(
																																		gl_panel.createSequentialGroup()
																																				.addGroup(
																																						gl_panel.createParallelGroup(
																																								Alignment.LEADING)
																																								.addComponent(
																																										lblInitialFpsolution)
																																								.addComponent(
																																										lblFinalFpsolution))
																																				.addGap(68)
																																				.addGroup(
																																						gl_panel.createParallelGroup(
																																								Alignment.LEADING)
																																								.addComponent(
																																										finalResullt,
																																										GroupLayout.PREFERRED_SIZE,
																																										GroupLayout.DEFAULT_SIZE,
																																										GroupLayout.PREFERRED_SIZE)
																																								.addComponent(
																																										initialResult,
																																										GroupLayout.PREFERRED_SIZE,
																																										GroupLayout.DEFAULT_SIZE,
																																										GroupLayout.PREFERRED_SIZE))
																																				.addGap(153))
																																.addGroup(
																																		gl_panel.createSequentialGroup()
																																				.addComponent(
																																						lblInitialSolutionWas)
																																				.addGap(18)
																																				.addComponent(
																																						btnRunSA)))))))
												.addGroup(
														gl_panel.createSequentialGroup()
																.addGap(64)
																.addComponent(
																		lblClickToRun)
																.addPreferredGap(
																		ComponentPlacement.UNRELATED)
																.addComponent(
																		repeatSA)))
								.addContainerGap(45, Short.MAX_VALUE)));
		gl_panel.setVerticalGroup(gl_panel
				.createParallelGroup(Alignment.TRAILING)
				.addGroup(
						gl_panel.createSequentialGroup()
								.addContainerGap(GroupLayout.DEFAULT_SIZE,
										Short.MAX_VALUE)
								.addComponent(lblPowerawareFloorplanning,
										GroupLayout.PREFERRED_SIZE, 54,
										GroupLayout.PREFERRED_SIZE)
								.addGroup(
										gl_panel.createParallelGroup(
												Alignment.LEADING)
												.addGroup(
														gl_panel.createSequentialGroup()
																.addGap(26)
																.addComponent(
																		btnRunSA))
												.addGroup(
														gl_panel.createSequentialGroup()
																.addGap(50)
																.addComponent(
																		lblInitialSolutionWas)
																.addGap(38)
																.addComponent(
																		label)
																.addGap(21)
																.addComponent(
																		lblSimulatedAnnealingResults)
																.addGap(36)
																.addGroup(
																		gl_panel.createParallelGroup(
																				Alignment.BASELINE)
																				.addComponent(
																						lblInitialFpsolution)
																				.addComponent(
																						initialResult,
																						GroupLayout.PREFERRED_SIZE,
																						GroupLayout.DEFAULT_SIZE,
																						GroupLayout.PREFERRED_SIZE))
																.addGap(34)
																.addGroup(
																		gl_panel.createParallelGroup(
																				Alignment.BASELINE)
																				.addComponent(
																						lblFinalFpsolution)
																				.addComponent(
																						finalResullt,
																						GroupLayout.PREFERRED_SIZE,
																						GroupLayout.DEFAULT_SIZE,
																						GroupLayout.PREFERRED_SIZE))))
								.addPreferredGap(ComponentPlacement.RELATED,
										45, Short.MAX_VALUE)
								.addGroup(
										gl_panel.createParallelGroup(
												Alignment.TRAILING)
												.addGroup(
														gl_panel.createSequentialGroup()
																.addComponent(
																		lblClickToRun)
																.addGap(48))
												.addGroup(
														gl_panel.createSequentialGroup()
																.addComponent(
																		repeatSA)
																.addGap(39)))));
		panel.setLayout(gl_panel);
		getContentPane().setLayout(groupLayout);

		mntmSimulatedAnnealingResult.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (soluion == null
						|| (soluion.getSimulatedAnnealingAlg()
								.getMidWayFinalSolution().size() == 0)) {
					JOptionPane
							.showMessageDialog(
									myFrame,
									"In order to see the FP, Simulated Annealing algorithm must be executed first");
				}
				
				else{
					double totalHorLength = 0.0;
					double totalVerLength = 0.0;

					for (Block b : soluion.getSimulatedAnnealingAlg().getSolution()
							.getBlocks().values()) {
						totalHorLength += b.getHorizontalLength();
						totalVerLength += b.getVerticalLength();
					}

					JFrame fp = new JFrame();
					fp.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
					fp.getContentPane().add(
							new FpDraw(soluion.getSimulatedAnnealingAlg()
									.getSolution().getBlocks()));
					fp.setSize((int) (totalHorLength + 1) * 30,
							(int) (totalVerLength + 1) * 30);
					fp.setLocation(300, 300);
					fp.setVisible(true);
				}	
			}
		});

		btnRunSA.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				soluion.executeSA();
				lblInitialSolutionWas.setVisible(false);
				btnRunSA.setVisible(false);
				lblFinalFpsolution.setVisible(true);
				lblInitialFpsolution.setVisible(true);
				lblSimulatedAnnealingResults.setVisible(true);
				initialResult.setVisible(true);
				finalResullt.setVisible(true);
				lblClickToRun.setVisible(true);
				repeatSA.setVisible(true);

				BigDecimal bd = new BigDecimal(initialFloorPlan
						.calculatePowerFloorPlanCost());
				bd = bd.setScale(5, BigDecimal.ROUND_HALF_UP);
				initialResult.setText(String.valueOf(bd.doubleValue()));

				BigDecimal finalBd = new BigDecimal(soluion
						.getSimulatedAnnealingAlg().getSolution()
						.calculatePowerFloorPlanCost());
				finalBd = finalBd.setScale(5, BigDecimal.ROUND_HALF_UP);
				finalResullt.setText(String.valueOf(finalBd.doubleValue()));

				initialResult.setEditable(false);
				finalResullt.setEditable(false);
			}
		});

		repeatSA.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {

				soluion.setSimulatedAnnealingAlg(new SimulatedAnnealing());
				soluion.executeSA();

				BigDecimal bd = new BigDecimal(initialFloorPlan
						.calculatePowerFloorPlanCost());
				bd = bd.setScale(5, BigDecimal.ROUND_HALF_UP);
				initialResult.setText(String.valueOf(bd.doubleValue()));

				BigDecimal finalBd = new BigDecimal(soluion
						.getSimulatedAnnealingAlg().getSolution()
						.calculatePowerFloorPlanCost());
				finalBd = finalBd.setScale(5, BigDecimal.ROUND_HALF_UP);
				finalResullt.setText(String.valueOf(finalBd.doubleValue()));
			}
		});

		btnShowGraph.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {

				if (soluion == null
						|| (soluion.getSimulatedAnnealingAlg()
								.getMidWayFinalSolution().size() == 0)) {
					JOptionPane
							.showMessageDialog(
									myFrame,
									"To be able to see the graph Simulated Annealing algorithm must be executed first");
				}

				else {
					/*SimulatedPlot saPlot;
					JDialog dialog = new JDialog();
					saPlot = new SimulatedPlot(soluion);
			        dialog.setContentPane(saPlot);
			        dialog.setModal(true);
			        dialog.pack();
			        dialog.setLocationRelativeTo(myFrame);
			        dialog.setVisible(true);*/
				}
			}
		});

		insertFileInput.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				JFileChooser browser = new JFileChooser();
				File selectedFile;
				browser.showOpenDialog(MainPage.this);

				selectedFile = browser.getSelectedFile();

				if (selectedFile == null)
					return;

				try {

					FloorPlanParser parse = new FloorPlanParser(selectedFile);

					if (parse.getResult() != ParseResult.PARSE_SUCCESS) {
						JOptionPane
								.showMessageDialog(myFrame,
										"There was an error parsing the input file, please try again");
					}

					else {
						initialFloorPlan = parse.getFloorPlan();
						SAconfigurations config = new SAconfigurations();

						soluion = new Solution(initialFloorPlan,
								alogrithmToUse.SIMULATED_ANNEALING, config);

						lblInitialSolutionWas.setVisible(true);
						btnRunSA.setVisible(true);
					}
					/*
					 * initialFloorPlan = parse.getFloorPlan();
					 * 
					 * soluion =
					 * 
					 * BigDecimal bd = new BigDecimal(initialFloorPlan
					 * .calculatePowerFloorPlanCost()); bd = bd.setScale(5,
					 * BigDecimal.ROUND_HALF_UP);
					 * 
					 * initialCost.setText(String.valueOf(bd.doubleValue()));
					 * SimulatedAnnealing sa = new SimulatedAnnealing();
					 * SAconfigurations config = new SAconfigurations();
					 * sa.executeAlgorithm(initialFloorPlan, config);
					 * 
					 * BigDecimal finalBd = new BigDecimal(sa.getSolution()
					 * .calculatePowerFloorPlanCost()); finalBd =
					 * finalBd.setScale(5, BigDecimal.ROUND_HALF_UP);
					 * 
					 * finalCost.setText(String.valueOf(finalBd.doubleValue()));
					 * 
					 * Double[] arr = new
					 * Double[sa.getMidWaySolutions().size()]; arr =
					 * sa.getMidWaySolutions().toArray(arr);
					 */
					/*
					 * JFrame f = new JFrame();
					 * f.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
					 * f.getContentPane().add(new CostFunctionGraph(arr));
					 * f.setSize(400, 400); f.setLocation(200, 200);
					 * f.setVisible(true);
					 * 
					 * 
					 * double totalHorLength=0.0; double totalVerLength=0.0;
					 * for(Block b : sa.getSolution().getBlocks().values()){
					 * totalHorLength += b.getHorizontalLength(); totalVerLength
					 * += b.getVerticalLength(); }
					 * 
					 * JFrame fp = new JFrame();
					 * fp.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
					 * fp.getContentPane().add(new
					 * FpDraw(sa.getSolution().getBlocks()));
					 * fp.setSize((int)(totalHorLength+1)*30,
					 * (int)(totalVerLength+1)*30); fp.setLocation(300, 300);
					 * fp.setVisible(true);
					 */

				} catch (IOException e) {
					JOptionPane
							.showMessageDialog(myFrame,
									"There was an error parsing the input file, please try again");
				} catch (NullPointerException e) {
					JOptionPane
							.showMessageDialog(myFrame,
									"There was an error parsing the input file, please try again");
				}
			}
		});
	}

	protected void configurationsUpdateDialog() {
		if (soluion == null) {
			JOptionPane
					.showMessageDialog(this,
							"You must have an initial FP first, Go to File -> Choose Initial FP");
		} else {
			UserConfigurations configurationsPanel;
			JDialog dialog = new JDialog();
			configurationsPanel = new UserConfigurations(dialog, soluion);
			dialog.setContentPane(configurationsPanel);
			dialog.setTitle("Configurations");
			dialog.setModal(true);
			dialog.setModalExclusionType(ModalExclusionType.APPLICATION_EXCLUDE);
			dialog.pack();
			dialog.setLocationRelativeTo(this);
			dialog.setVisible(true);
		}
	}
}
